#include <iostream>
#include <vector>
#include <pthread.h>
#include "Sem.hpp"
using namespace std;

const int defaultNum = 5 ;


template<class T>
class CycQueue
{
private:

    vector<T> _cyc_queue;
    int _num;      //循环队列大小
    int _c_step; //消费下标
    int _p_step ; //生产下标
    Sem _space_sem;
    Sem _data_sem ;
    pthread_mutex_t _clock ;
    pthread_mutex_t _plock;

public:

    CycQueue(int default_num = defaultNum)   
        :_c_step(0)
        ,_p_step(0)
        ,_num(default_num)
        ,_space_sem(default_num)
        ,_data_sem(0)
        ,_cyc_queue(default_num)  // 还有这种写法……… ？ ？  ？ ？
    {
        pthread_mutex_init(&_clock,nullptr);
        pthread_mutex_init(&_plock,nullptr);
    }


    //生产者
    void push(const T& in)  //输入型参数
    {
        // 先申请信号量 , 再加锁(必须)
        _space_sem.p();
        pthread_mutex_lock(&_plock);

        // 同时只有一个在生产/发布任务 
        _cyc_queue[_p_step] = in ; 
        _p_step++ ; 

        // 这里信号量归还和锁的释放似乎没有严格的要求。  是否会导致其他线程不阻塞在_space_sem.p(); 而阻塞在pthread_mutex_lock(&_clock); 导致更多的执行资源浪费 ？ 
        //个人感觉不会因为这两个阻塞的原理似乎一样，也就是说对执行资源的消耗差不多
        pthread_mutex_unlock(&_plock);
        _space_sem.v();
    }

    //消费者 
    void pop(T* out)  // 输出型参数   // 取出数据
    {
        _data_sem.p();
        pthread_mutex_lock(&_clock);
        
        *out =  _cyc_queue[_c_step] ;
        _c_step++;
        _c_step = _c_step % _num;
        pthread_mutex_unlock(&_clock);
        _data_sem.v();
    }

    ~CycQueue()
    {
        pthread_mutex_destroy(&_plock);
        pthread_mutex_destroy(&_clock);
    }

};





















